// 工具函数库

const utils = {
  //存储toast的定时器
  toastTimer: null,
  /**
   * [pick 从对象中取出特定项，返回新对象]
   * @Author   罗文
   * @DateTime 2018-09-28
   * @param    {[Object]}   obj        [目标对象]
   * @param    {[Array]}   filtersArr [要筛选的键数组]
   * @return   {[type]}              [description]
   */
  pick(obj, keysArr) {
    let newObj = {}
    let keys = Object.keys(obj)

    keysArr.forEach(key => {
      let isInclude = keys.includes(key)
      if (isInclude) newObj[key] = obj[key]
    })

    return newObj
  },

  /**
   * 获取url参数
   * @param {string} query url参数
   * @return {object} url参数对象
   * @example
   * util.getQuery('lechebang.com?key=value&city=3')
   * util.getQuery(location.search)
   * // 如果参数里面有url或者中文，请先自行先encodeURIComponent字符串
   */
  getQuery(query) {
    let ret = {}
    let searchReg = /([^&=?]+)=([^&]+)/g
    let name, value
    let match = searchReg.exec(query)

    while (match) {
      name = match[1]
      value = match[2]
      ret[name] = decodeURIComponent(value)
      match = searchReg.exec(query)
    }

    return ret
  },

  dateFormat: _dateFormatExec(),

  //创建一个轻提示
  showToast(msg) {
    if (this.toastTimer) {
      document.getElementsByClassName('zl-toast-msg')[0].innerText = msg

      //重新开启一个2秒的定时器
      clearTimeout(this.toastTimer)
      this.toastTimer = setTimeout(() => {
        let cur = document.getElementById('zlToast')
        cur.parentNode.removeChild(cur)
        this.toastTimer = null
      }, 2000)

      return
    }

    let toast = document.createElement('div')
    toast.className =
      'black-overlay flex-center-wrap flex-justify-center zl-toast'
    toast.setAttribute('id', 'zlToast')
    toast.innerHTML = `
      <div class="flex-center-wrap flex-justify-center zl-toast-cont">
            <div class="zl-toast-msg">
              ${msg}
            </div>
          </div>
    `
    document.getElementById('app').appendChild(toast)

    this.toastTimer = setTimeout(() => {
      let cur = document.getElementById('zlToast')
      cur.parentNode.removeChild(cur)
      clearTimeout(this.toastTimer)
      this.toastTimer = null
    }, 2000)
  },

  //销毁轻提示
  hideToast() {
    clearTimeout(this.toastTimer)
    let cur = document.getElementById('zlToast')
    cur.parentNode.removeChild(cur)
    this.toastTimer = null
  }
}

function _dateFormatExec() {
  let dateFormat = function() {
    let token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZWNC]|'[^']*'|'[^']*'/g
    let timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g
    let timezoneClip = /[^-+\dA-Z]/g

    // Regexes and supporting functions are cached through closure
    return function(date, mask, utc, gmt) {
      // You can't provide utc if you skip other args (use the 'UTC:' mask prefix)
      if (
        arguments.length === 1 &&
        kindOf(date) === 'string' &&
        !/\d/.test(date)
      ) {
        mask = date
        date = undefined
      }

      date = date || new Date()

      if (!(date instanceof Date)) {
        date = new Date(date)
      }

      if (isNaN(date)) {
        throw TypeError('Invalid date')
      }

      mask = String(
        dateFormat.masks[mask] || mask || dateFormat.masks['default']
      )

      // Allow setting the utc/gmt argument via the mask
      let maskSlice = mask.slice(0, 4)
      if (maskSlice === 'UTC:' || maskSlice === 'GMT:') {
        mask = mask.slice(4)
        utc = true
        if (maskSlice === 'GMT:') {
          gmt = true
        }
      }

      let _ = utc ? 'getUTC' : 'get'
      let d = date[_ + 'Date']()
      let D = date[_ + 'Day']()
      let m = date[_ + 'Month']()
      let y = date[_ + 'FullYear']()
      let H = date[_ + 'Hours']()
      let M = date[_ + 'Minutes']()
      let s = date[_ + 'Seconds']()
      let L = date[_ + 'Milliseconds']()
      let o = utc ? 0 : date.getTimezoneOffset()
      let W = getWeek(date)
      let N = getDayOfWeek(date)
      let flags = {
        d: d,
        dd: pad(d),
        ddd: dateFormat.i18n.dayNames[D],
        dddd: dateFormat.i18n.dayNames[D + 7],
        m: m + 1,
        mm: pad(m + 1),
        mmm: dateFormat.i18n.monthNames[m],
        mmmm: dateFormat.i18n.monthNames[m + 12],
        yy: String(y).slice(2),
        yyyy: y,
        h: H % 12 || 12,
        hh: pad(H % 12 || 12),
        H: H,
        HH: pad(H),
        M: M,
        MM: pad(M),
        s: s,
        ss: pad(s),
        l: pad(L, 3),
        L: pad(Math.round(L / 10)),
        t: H < 12 ? 'a' : 'p',
        tt: H < 12 ? 'am' : 'pm',
        T: H < 12 ? 'A' : 'P',
        TT: H < 12 ? 'AM' : 'PM',
        Z: gmt
          ? 'GMT'
          : utc
          ? 'UTC'
          : (String(date).match(timezone) || [''])
              .pop()
              .replace(timezoneClip, ''),
        o:
          (o > 0 ? '-' : '+') +
          pad(Math.floor(Math.abs(o) / 60) * 100 + (Math.abs(o) % 60), 4),
        S: ['th', 'st', 'nd', 'rd'][
          d % 10 > 3 ? 0 : (((d % 100) - (d % 10) !== 10) * d) % 10
        ],
        W: W,
        N: N,
        C: ['日', '一', '二', '三', '四', '五', '六', '日'][N]
      }

      return mask.replace(token, function(match) {
        if (match in flags) {
          return flags[match]
        }
        return match.slice(1, match.length - 1)
      })
    }
  }

  dateFormat.masks = {
    default: 'ddd mmm dd yyyy HH:MM:ss',
    shortDate: 'm/d/yy',
    mediumDate: 'mmm d, yyyy',
    longDate: 'mmmm d, yyyy',
    fullDate: 'dddd, mmmm d, yyyy',
    shortTime: 'h:MM TT',
    mediumTime: 'h:MM:ss TT',
    longTime: 'h:MM:ss TT Z',
    isoDate: 'yyyy-mm-dd',
    isoTime: 'HH:MM:ss',
    isoDateTime: "yyyy-mm-dd'T'HH:MM:sso",
    isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'",
    expiresHeaderFormat: 'ddd, dd mmm yyyy HH:MM:ss Z'
  }

  // Internationalization strings
  dateFormat.i18n = {
    dayNames: [
      'Sun',
      'Mon',
      'Tue',
      'Wed',
      'Thu',
      'Fri',
      'Sat',
      'Sunday',
      'Monday',
      'Tuesday',
      'Wednesday',
      'Thursday',
      'Friday',
      'Saturday'
    ],
    monthNames: [
      'Jan',
      'Feb',
      'Mar',
      'Apr',
      'May',
      'Jun',
      'Jul',
      'Aug',
      'Sep',
      'Oct',
      'Nov',
      'Dec',
      'January',
      'February',
      'March',
      'April',
      'May',
      'June',
      'July',
      'August',
      'September',
      'October',
      'November',
      'December'
    ]
  }

  function pad(val, len) {
    val = String(val)
    len = len || 2
    while (val.length < len) {
      val = '0' + val
    }
    return val
  }

  /**
   * Get the ISO 8601 week number
   * Based on comments from
   * http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html
   *
   * @param  {Object} `date`
   * @return {Number}
   */
  function getWeek(date) {
    // Remove time components of date
    let targetThursday = new Date(
      date.getFullYear(),
      date.getMonth(),
      date.getDate()
    )

    // Change date to Thursday same week
    targetThursday.setDate(
      targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3
    )

    // Take January 4th as it is always in week 1 (see ISO 8601)
    let firstThursday = new Date(targetThursday.getFullYear(), 0, 4)

    // Change date to Thursday same week
    firstThursday.setDate(
      firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3
    )

    // Check if daylight-saving-time-switch occured and correct for it
    let ds =
      targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset()
    targetThursday.setHours(targetThursday.getHours() - ds)

    // Number of weeks between target Thursday and first Thursday
    let weekDiff = (targetThursday - firstThursday) / (86400000 * 7)
    return 1 + Math.floor(weekDiff)
  }

  /**
   * Get ISO-8601 numeric representation of the day of the week
   * 1 (for Monday) through 7 (for Sunday)
   *
   * @param  {Object} `date`
   * @return {Number}
   */
  function getDayOfWeek(date) {
    let dow = date.getDay()
    if (dow === 0) {
      dow = 7
    }
    return dow
  }

  /**
   * kind-of 判断一个变量的类型
   * @param  {*} val
   * @return {String}
   */
  function kindOf(val) {
    if (val === null) {
      return 'null'
    }

    if (val === undefined) {
      return 'undefined'
    }

    if (typeof val !== 'object') {
      return typeof val
    }

    if (Array.isArray(val)) {
      return 'array'
    }

    return {}.toString
      .call(val)
      .slice(8, -1)
      .toLowerCase()
  }
  return dateFormat()
}

// 单选题判题方法
function radioCheck(params) {
  const obj = {}
  const { selectAnswer, answer, score, pointrules } = params
  let getScore = score
  let deductScore = 0
  // 做错不得分也不扣分
  if (pointrules === 1 || pointrules === 2) {
    if (selectAnswer === '') {
      obj.answerStatu = 'undone'
      getScore = 0
    } else if (selectAnswer === answer) {
      obj.answerStatu = 'right'
    } else if (selectAnswer !== answer) {
      obj.answerStatu = 'wrong'
      getScore = 0
    }
  }
  // 做错不得分扣分
  if (pointrules === 3 || pointrules === 4) {
    if (selectAnswer === '') {
      obj.answerStatu = 'undone'
      getScore = 0
    } else if (selectAnswer === answer) {
      obj.answerStatu = 'right'
    } else if (selectAnswer !== answer) {
      obj.answerStatu = 'wrong'
      getScore = 0
      deductScore = -getScore
    }
  }
  obj.getScore = getScore
  obj.deductScore = deductScore
  // 如果此题不计分 则返回对应的分数
  obj.noJudegeScore = 0
  return obj
}

// 多选题判题方法
function checkboxCheck(params) {
  const obj = {}
  // type 0为多选题 1为不定选
  const { selectAnswer, answer, score, pointrules } = params
  let getScore = score
  let deductScore = 0
  // 多选、少选、错选不得分
  if (pointrules === 1 || pointrules === 2) {
    if (selectAnswer.length !== answer.length) {
      obj.answerStatu = 'wrong'
      obj.getScore = 0
      obj.deductScore = 0
      // 如果此题不计分 则返回对应的分数
      obj.noJudegeScore = 0
      return obj
    } else {
      for (let item of selectAnswer) {
        if (answer.includes(item) === false) {
          obj.answerStatu = 'wrong'
          obj.getScore = 0
          obj.deductScore = 0
          // 如果此题不计分 则返回对应的分数
          obj.noJudegeScore = 0
          return obj
        }
      }
      obj.answerStatu = 'right'
      obj.getScore = score
      obj.deductScore = 0
      // 如果此题不计分 则返回对应的分数
      obj.noJudegeScore = 0
      return obj
    }
  }
  // 只要不全对就扣分
  if (pointrules === 3) {
    if (selectAnswer.length !== answer.length) {
      obj.answerStatu = 'wrong'
      obj.getScore = 0
      obj.deductScore = -getScore
      return obj
    } else {
      for (let item of selectAnswer) {
        if (answer.includes(item) === false) {
          obj.answerStatu = 'wrong'
          obj.getScore = 0
          obj.deductScore = -getScore
          // 如果此题不计分 则返回对应的分数
          obj.noJudegeScore = 0
          return obj
        }
      }
      obj.answerStatu = 'right'
      obj.getScore = score
      obj.deductScore = 0
      // 如果此题不计分 则返回对应的分数
      obj.noJudegeScore = 0
      return obj
    }
  }
  // 半对不扣分，错了扣分
  if (pointrules === 4) {
    if (selectAnswer.length !== answer.length) {
      let wrongSelect = 0
      for (let item of selectAnswer) {
        if (answer.includes(item) === false) {
          wrongSelect += 1
        }
      }
      // 多选或错选
      if (wrongSelect > 0) {
        obj.answerStatu = 'wrong'
        obj.getScore = 0
        obj.deductScore = -getScore
        // 如果此题不计分 则返回对应的分数
        obj.noJudegeScore = 0
        return obj
      } else {
        // 半对
        obj.answerStatu = 'halfRight'
        obj.getScore = 0
        obj.deductScore = 0
        // 如果此题不计分 则返回对应的分数
        obj.noJudegeScore = 0
        return obj
      }
    } else {
      for (let item of selectAnswer) {
        if (answer.includes(item) === false) {
          obj.answerStatu = 'wrong'
          obj.getScore = 0
          obj.deductScore = -getScore
          // 如果此题不计分 则返回对应的分数
          obj.noJudegeScore = 0
          return obj
        }
      }
      obj.answerStatu = 'right'
      obj.getScore = score
      obj.deductScore = 0
      // 如果此题不计分 则返回对应的分数
      obj.noJudegeScore = 0
      return obj
    }
  }
}
// 简单题判断方法
function fieldCheck(params) {
  const obj = {}
  // type 0为多选题 1为不定选
  const { score, pointrules } = params
  obj.answerStatu = 'noJudge'
  obj.getScore = 0
  obj.deductScore = 0
  // 如果此题不计分 则返回对应的分数
  obj.noJudegeScore = -score
  return obj
}

// 时间计算
function calcTime(time) {
  let hours = parseInt(time / 3600, 10)
  if (hours < 10) {
    hours = '0' + hours
  } else {
  }
  let minutes = parseInt((time - hours * 3600) / 60, 10)
  if (minutes < 10) {
    minutes = '0' + minutes
  } else {
  }
  let seconds = parseInt(time - hours * 3600 - minutes * 60, 10)
  if (seconds < 10) {
    seconds = '0' + seconds
  } else {
  }
  return `${hours}:${minutes}:${seconds}`
}
